/*
  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  PARTICULAR PURPOSE.
  
    This is sample code and is freely distributable.
*/

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using svs.Mobile.BeyondMedia.FeedCore;
using svs.Mobile.BeyondMedia.FeedCore.Helpers;
using svs.Mobile.BeyondMedia.GraphicsAPI;
using svs.Mobile.BeyondMedia.Objects;
using svs.Mobile.BeyondMedia.Properties;

namespace svs.Mobile.BeyondMedia.Controls
{
	/// <summary>
	/// Provide a 2 line listview
	/// </summary>
	internal class PlayListView : OwnerDrawnList<Track>
	{
		private const int IMAGE_WIDTH = 16;
		private const int IMAGE_HEIGHT = 16;
		private int m_AnimationFrame = 0;
		private const int Column1Left = 5;
		private const int Column2Left = 25;
		private const int FONT_SIZE = 9;
		private readonly TrackList m_TrackList = new TrackList();

		public event Helpers.TrackSelectedEvent TrackSelected;

		public PlayListView()
		{
			// We need a total of 5 rows, so the height is 180/5=36
			using (Graphics g = CreateGraphics())
			{
				using (Font font = new Font(Font.Name, FONT_SIZE, FontStyle.Bold))
				{
					// Calc line height to be height of letter A plus 10%
					int fontHeight = (int) (g.MeasureString("A", font).Height*1.1);
					ItemHeight = Math.Max(fontHeight, Resources.track.Height + 2);
				}
			}
			EnableKeyNavigation = false;
			
			FeedRepository.TrackDeleted += OnTrackDeleted;
			FeedRepository.TrackChanged += OnTrackChanged;

			ItemSeparatorColor = Color.Silver;
		}

		private void OnTrackChanged(Track aTrack)
		{
			if (InvokeRequired)
			{
				TrackUpdatedDelegate cbDel = OnTrackChanged;
				Invoke(cbDel, aTrack);
				return;
			}

			int i = m_TrackList.IndexOf(aTrack);

			if(i == -1)
				return;

			if (SelectedIndex != i)
			{
				SelectedIndex = i;
			}

			EnsureVisible(SelectedIndex);
		}

		private delegate void TrackUpdatedDelegate(Track i_track);
		private void OnTrackDeleted(Track i_track)
		{
			if (InvokeRequired)
			{
				TrackUpdatedDelegate cbDel =OnTrackDeleted;
				Invoke(cbDel, i_track);
				return;
			}

			if (m_TrackList.Contains(i_track))
			{
				Items.Remove(i_track);
				m_TrackList.Remove(i_track);

				//Make sure the Selected index is handled correctly
				if (SelectedIndex >= m_TrackList.Count)
					SelectedIndex = -1;
			}

			Refresh();
			OnResize(null);
		}

		public TrackList Tracks
		{
			set
			{
				Clear();
				m_TrackList.AddRange(value);
				Items.AddRange(value);
				OnResize(null);
			}
			get { return m_TrackList; }
		}

		/// <summary>
		/// Custom OnPaint. This paints the listview items
		/// </summary>
		/// <param name="e"></param>
		protected override void OnPaint(PaintEventArgs e)
		{
			// Declare vars
			Font font;
			Bitmap bmp;

			// Get graphics object from bitmap.
			using (Graphics gOffScreen = PrepareOffscreenGraphics())
			{
				// Set the y pos of the current item
				int itemTop = 0;

				// Draw the visible items.
				for (int n = VScrollBar.Value; n <= VScrollBar.Value + DrawCount; n++)
				{
					Rectangle itemArea;
					itemArea = new Rectangle(0,
					                         itemTop,
					                         ClientSize.Width - (VScrollBar.Visible ? VScrollBar.Width : 0),
					                         ItemHeight);
					if (n > Items.Count - 1)
						break;

					// Get the current MailItem
					Track track = (Track) Items[n];

					DrawItemBox(gOffScreen, ItemSeparatorColor, itemArea, track.PlayedAsFraction);

					ImageAttributes ia = new ImageAttributes();
					if (n == SelectedIndex)
					{
						if (track.CurrentPlayState == Track.PlayMode.Play)
							bmp = Resources.play;
						else
							bmp = Resources.pause;

						ia.SetColorKey(Color.Red, Color.Red);
					}
					else if (track.DownloadStatus == Track.DownloadStatuses.Downloading)
					{
						bmp = Resources.downloading;
						ia.SetColorKey(Color.Red, Color.Red);
					}
					else
					{
						ia.SetColorKey(Color.White, Color.White);
						bmp = Helpers.GetTrackIcon(track);
					}

					// Set the image rectangle
					int imgTop = (ItemHeight/2) - (bmp.Height/2);
					if (imgTop < 0)
						imgTop = 0;

					Rectangle imgRect;

					// Draw the image
					if (track.DownloadStatus == Track.DownloadStatuses.Downloading)
					{
						int currentFrame = 0;

						m_AnimationFrame++;
						int numFrames = bmp.Width/IMAGE_WIDTH;
						if (m_AnimationFrame >= numFrames)
							m_AnimationFrame = 0;

						currentFrame = m_AnimationFrame;

						imgRect = new Rectangle(Column1Left, itemTop + imgTop, IMAGE_WIDTH, IMAGE_HEIGHT);
						gOffScreen.DrawImage(bmp, imgRect, currentFrame*IMAGE_WIDTH, 0, IMAGE_WIDTH, IMAGE_HEIGHT, GraphicsUnit.Pixel, ia);
					}
					else
					{
						imgRect = new Rectangle(Column1Left, itemTop + imgTop, bmp.Width, bmp.Height);
						gOffScreen.DrawImage(bmp, imgRect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, ia);
					}

					font = new Font(Font.Name, FONT_SIZE, FontStyle.Regular);
					SizeF timeSize = gOffScreen.MeasureString(track.TotalTimeAsString, font);
					Rectangle nameRect =
						new Rectangle(imgRect.Right + 4, itemTop, itemArea.Width - (Column2Left + (int) timeSize.Width + 3), ItemHeight);

					StringFormat sf = new StringFormat();
					sf.Alignment = StringAlignment.Near;
					sf.LineAlignment = StringAlignment.Far;
					//Draw the track name

					using (Brush b = new SolidBrush(ForeColor))
					{
						gOffScreen.DrawString(track.Name,font,b, nameRect, sf);
					}

					//Draw the track time
					Rectangle timeRect = new Rectangle(nameRect.Right + 3, itemTop, (int) timeSize.Width, ItemHeight);
					sf.Alignment = StringAlignment.Far;
					sf.LineAlignment = StringAlignment.Far;
					if (track.TotalTime > 0)
					{
						using (Brush b = new SolidBrush(ForeColor))
						{
							gOffScreen.DrawString(track.TotalTimeAsString, font, b, timeRect, sf);
						}
					}
					// Cleanup
					font.Dispose();
					bmp.Dispose();

					// Set the next item top to move down the item height
					itemTop += ItemHeight + 1;
				}

				// Now draw the visible list box
				e.Graphics.DrawImage(OffScreen, 0, 0);
			}

			base.OnPaint(e);
		}

		// Draws the external border around the control.    
		protected override void OnPaintBackground(PaintEventArgs e)
		{
			//			e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
		}

		protected override void ItemClicked(int i_ItemIndex, int X, int Y, DragHelper.ClickSpeed speed)
		{
			if (i_ItemIndex >= 0 && i_ItemIndex < m_TrackList.Count && TrackSelected != null)
				TrackSelected(m_TrackList[i_ItemIndex]);
		}

		/// <summary>
		/// Clears this instance.
		/// </summary>
		public void Clear()
		{
			SelectedIndex = -1;
			m_TrackList.Clear();
			Items.Clear();
		}

		private void DrawItemBox(Graphics g, Color lineColor, Rectangle rc, float percentPlayed)
		{
			using (Pen linePen = new Pen(lineColor))
			{
				g.DrawLine(linePen, rc.Left,
									 rc.Bottom,
									 rc.Right,
									 rc.Bottom);
			}

			if (percentPlayed > 0)
			{
				float width = rc.Width;
				width *= percentPlayed;

				Rectangle highlighted = new Rectangle(rc.Left, rc.Top, (int)Math.Floor(width), rc.Height);
				GradientFill.Fill(g, highlighted, BackColor, Helpers.ChangeColorIntensity(BackColor, 0.75), GradientFill.FillDirection.LeftToRight);
			}
		}


	}
}